0. Introdução¶

Nessa análise tive uma abordagem um pouco mais explicativa, em um formato similar ao de um tutorial ou artigo, voltada a um público que não tem familiaridade com a área dados. Escolhi isso por ser meu primeiro projeto de análise exploratória e por interesse em aproveitá-la para criar um artigo que será postado na plataforma Medium.

Análise exploratória dos dados do FIFA 23¶

Primeiramente, precisamos entender o que é uma análise exploratória. A análise exploratória de dados (EDA) é o processo de examinar um conjunto de dados, buscando compreendê-lo de forma geral para entender suas principais características e padrões antes de aplicar técnicas mais avançadas de estatística ou de machine learning. Ele extremamente comum na rotina de Analistas e Cientistas de dados, sendo uma etapa bem importante nos projetos desenvolvidos desses profissionais.

Nesta análise, pretendo utilizar algumas funções da biblioteca Plotly, que nos permite criar gráficos interativos de maneira bem simples, e responder algumas e perguntas e hipóteses que criei sobre os dados com ajuda deles. Para manipular os dados utilizei a biblioteca Pandas do python no ambiente local do Jupyter Notebook do Anaconda Navigator.

Sobre os dados: Os dados que iremos analisar são do video-game de futebol FIFA 23. Todos os registros são sobre os jogadores contidos no jogo, como, por exemplo: Nome, Idade, Nome do Clube, Valor, Salário, Nacionalidade e Overall.

Um termo que será muito comum aqui será Overall (também chamado de rating) . Esse é o atributo principal de um jogador, que define sua qualidade geral. Ele varia normalmente entre 50 e 95, sendo que os considerados bons jogadores têm um valor de rating de 80 ou superior. Similiar a esse atributo, temos o Overall potencial , que é o valor de rating máximo, definido pelos desenvolvedores, que um jogador pode atingir em sua carreira. Ele costuma ser elevado para jogadores mais jovens e igual, ou pouco superior, para jogadores mais velhos. Além desses, existem diversos atributos que medem os atributos físicos, de habilidade e mentais dos atletas. Uma explicação mais detalhada sobre alguns deles pode ser encontrada neste link: https://fifauteam.com/fifa-23-attributes/

Importante lembrar que, o FIFA 23 não possui todos os jogadores profissionais registrados em sua base de dados (como os jogadores das ligas brasileiras, por exemplo), já que nem todas as ligas possuem contrato com a empresa desenvolvedora (EA Sports). Isso faz com que os dados não retratem 100% da realidade do futebol internacional, pois, além de não termos todos os atletas, naturalmente existem algumas imprecisões sobre a medição os atributos, e questionamentos se eles realmente correspondem as habilidades dos jogadores dentro de campo. Apesar dessas ressalvas, o Dataset (conjunto de dados) é bem completo e viável para ser feita uma boa análise.

Fonte dos dados: https://www.kaggle.com/datasets/sanjeetsinghnaik/fifa-23-players-dataset Autor: Sanjeetsinghnaik (Usuário do site "Kaggle")

Para guiar nossa análise exploratória

Perguntas e Hipóteses:

  • Quais países e clubes possuem maiores média de Overall?
  • Quais são os clubes mais valiosos e com maior folha salarial?
  • Quem são os jogadores mais habilidosos e rápidos do game?
  • Quais atributos mais influenciam no rating de um jogador?
  • Jogadores com estatísticas geral mais altas possuem maior Overall?
  • Os brasileiros e sulamericanos são os mais habilidosos?

1. Carregando Bibliotecas e o Dataset¶

In [1]:
#Importando as bibliotecas
import pandas as pd
import plotly.express as px
import plotly.figure_factory as ff
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.offline as pyo
pyo.init_notebook_mode(connected=True)
In [2]:
#Carregando dataset
df = pd.read_csv('Fifa 23 Players Data-Copy1.csv')
pd.set_option('display.max_columns', None)


#Removendo colunas desnecessárias para a análise
df.drop(['Image Link', 'National Team Image Link', 'National Team Jersey Number', 'Attacking Work Rate'
         , 'Defensive Work Rate', 'Contract Until', 'Joined On', 'On Loan', 'Skill Moves', 'Weak Foot Rating',
        'International Reputation'], 1, inplace = True)


#Mudando o nome de duas colunas para facilitar o uso
df.rename(columns={'Value(in Euro)':'Value','Wage(in Euro)':'Wage'}, inplace=True)
C:\Users\joaoi\AppData\Local\Temp\ipykernel_1292\212389229.py:7: FutureWarning:

In a future version of pandas all arguments of DataFrame.drop except for the argument 'labels' will be keyword-only.

In [3]:
df.head()
Out[3]:
Known As Full Name Overall Potential Value Positions Played Best Position Nationality Age Height(in cm) Weight(in kg) TotalStats BaseStats Club Name Wage Release Clause Club Position Club Jersey Number Preferred Foot National Team Name National Team Position Pace Total Shooting Total Passing Total Dribbling Total Defending Total Physicality Total Crossing Finishing Heading Accuracy Short Passing Volleys Dribbling Curve Freekick Accuracy LongPassing BallControl Acceleration Sprint Speed Agility Reactions Balance Shot Power Jumping Stamina Strength Long Shots Aggression Interceptions Positioning Vision Penalties Composure Marking Standing Tackle Sliding Tackle Goalkeeper Diving Goalkeeper Handling GoalkeeperKicking Goalkeeper Positioning Goalkeeper Reflexes ST Rating LW Rating LF Rating CF Rating RF Rating RW Rating CAM Rating LM Rating CM Rating RM Rating LWB Rating CDM Rating RWB Rating LB Rating CB Rating RB Rating GK Rating
0 L. Messi Lionel Messi 91 91 54000000 RW CAM Argentina 35 169 67 2190 452 Paris Saint-Germain 195000 99900000 RW 30 Left Argentina RW 81 89 90 94 34 64 84 90 70 91 88 95 93 93 90 93 87 76 91 92 95 86 68 70 68 91 44 40 93 94 75 96 20 35 24 6 11 15 14 8 90 90 91 91 91 90 91 91 88 91 67 66 67 62 53 62 22
1 K. Benzema Karim Benzema 91 91 64000000 CF,ST CF France 34 185 81 2147 455 Real Madrid CF 450000 131199999 CF 9 Right France ST 80 88 83 87 39 78 75 92 90 89 88 87 82 73 76 91 79 80 78 92 72 87 79 82 82 80 63 39 92 89 84 90 43 24 18 13 11 5 5 7 91 87 89 89 89 87 91 89 84 89 67 67 67 63 58 63 21
2 R. Lewandowski Robert Lewandowski 91 91 84000000 ST ST Poland 33 185 81 2205 458 FC Barcelona 420000 172200000 ST 9 Right Poland ST 75 91 79 86 44 83 71 94 91 84 89 85 79 85 70 89 76 75 77 93 82 91 85 76 87 84 81 49 94 81 90 88 35 42 19 15 6 12 8 10 91 85 88 88 88 85 88 86 83 86 67 69 67 64 63 64 22
3 K. De Bruyne Kevin De Bruyne 91 91 107500000 CM,CAM CM Belgium 31 181 70 2303 483 Manchester City 350000 198900000 CM 17 Right Belgium RF 74 88 93 87 64 77 94 85 55 93 83 88 89 83 93 90 76 73 76 91 78 92 63 88 74 91 75 66 88 94 83 89 68 65 53 15 13 5 10 13 86 88 87 87 87 88 91 91 91 91 82 82 82 78 72 78 24
4 K. Mbappé Kylian Mbappé 91 95 190500000 ST,LW ST France 23 182 73 2177 470 Paris Saint-Germain 230000 366700000 ST 7 Right France ST 97 89 80 92 36 76 78 93 72 85 83 93 80 69 71 91 97 97 93 93 81 88 77 87 76 82 64 38 92 83 80 88 26 34 32 13 5 7 11 6 92 90 90 90 90 90 92 92 84 92 70 66 70 66 57 66 21
In [4]:
df.tail()
Out[4]:
Known As Full Name Overall Potential Value Positions Played Best Position Nationality Age Height(in cm) Weight(in kg) TotalStats BaseStats Club Name Wage Release Clause Club Position Club Jersey Number Preferred Foot National Team Name National Team Position Pace Total Shooting Total Passing Total Dribbling Total Defending Total Physicality Total Crossing Finishing Heading Accuracy Short Passing Volleys Dribbling Curve Freekick Accuracy LongPassing BallControl Acceleration Sprint Speed Agility Reactions Balance Shot Power Jumping Stamina Strength Long Shots Aggression Interceptions Positioning Vision Penalties Composure Marking Standing Tackle Sliding Tackle Goalkeeper Diving Goalkeeper Handling GoalkeeperKicking Goalkeeper Positioning Goalkeeper Reflexes ST Rating LW Rating LF Rating CF Rating RF Rating RW Rating CAM Rating LM Rating CM Rating RM Rating LWB Rating CDM Rating RWB Rating LB Rating CB Rating RB Rating GK Rating
18534 D. Collins Darren Collins 47 56 110000 ST,RM CAM Republic of Ireland 21 174 68 1287 274 Sligo Rovers 500 193000 RES 20 Right - - 68 48 43 51 31 33 40 49 30 42 48 50 53 50 33 48 69 68 59 44 63 50 45 32 31 46 37 22 50 52 40 47 39 29 27 6 9 5 13 8 49 50 50 50 50 50 51 50 44 50 41 38 41 40 36 40 15
18535 Yang Dejiang Dejiang Yang 47 57 90000 CDM CDM China PR 17 175 60 1289 267 Guangzhou FC 500 158000 SUB 30 Right - - 55 37 41 47 48 39 34 33 44 46 31 42 32 31 45 46 52 57 59 51 80 50 55 34 35 35 52 46 35 40 33 45 46 50 52 6 12 11 8 6 44 43 43 43 43 43 45 45 45 45 47 48 47 49 49 49 15
18536 L. Mullan Liam Mullan 47 67 130000 CM RM Northern Ireland 18 170 65 1333 277 Derry City 500 332000 SUB 38 Right - - 64 40 49 52 37 35 41 36 42 54 37 52 47 42 52 50 70 59 46 49 73 54 54 36 31 36 39 24 42 50 43 59 39 37 48 11 12 8 7 12 48 49 49 49 49 49 51 52 49 52 46 44 46 46 42 46 17
18537 D. McCallion Daithí McCallion 47 61 100000 CB CB Republic of Ireland 17 178 65 1113 226 Derry City 500 218000 SUB 37 Right - - 52 24 25 32 52 41 21 20 41 25 27 27 26 20 22 26 53 51 42 43 66 34 72 49 34 18 42 54 23 32 37 41 50 54 54 8 14 13 7 8 33 30 30 30 30 30 31 33 33 33 44 42 44 47 49 47 15
18538 N. Rabha Nabin Rabha 47 50 60000 LB LB India 25 176 66 1277 269 NorthEast United FC 500 86000 RES 25 Left - - 61 29 35 46 44 54 38 28 41 35 29 47 33 32 29 38 70 53 58 45 76 29 66 56 55 28 47 40 36 39 35 32 47 44 43 13 13 6 14 14 41 42 40 40 40 42 42 44 40 44 46 43 46 47 47 47 19

3. Visão Geral¶

In [5]:
print("Este dataset possui {} linhas e {} colunas".format(df.shape[0],df.shape[1]))
Este dataset possui 18539 linhas e 78 colunas
In [6]:
#Valores únicos de cada coluna
df.nunique()
Out[6]:
Known As      17530
Full Name     18337
Overall          45
Potential        48
Value           257
              ...  
RWB Rating       72
LB Rating        71
CB Rating        73
RB Rating        71
GK Rating        64
Length: 78, dtype: int64
In [7]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 18539 entries, 0 to 18538
Data columns (total 78 columns):
 #   Column                  Non-Null Count  Dtype 
---  ------                  --------------  ----- 
 0   Known As                18539 non-null  object
 1   Full Name               18539 non-null  object
 2   Overall                 18539 non-null  int64 
 3   Potential               18539 non-null  int64 
 4   Value                   18539 non-null  int64 
 5   Positions Played        18539 non-null  object
 6   Best Position           18539 non-null  object
 7   Nationality             18539 non-null  object
 8   Age                     18539 non-null  int64 
 9   Height(in cm)           18539 non-null  int64 
 10  Weight(in kg)           18539 non-null  int64 
 11  TotalStats              18539 non-null  int64 
 12  BaseStats               18539 non-null  int64 
 13  Club Name               18539 non-null  object
 14  Wage                    18539 non-null  int64 
 15  Release Clause          18539 non-null  int64 
 16  Club Position           18539 non-null  object
 17  Club Jersey Number      18539 non-null  object
 18  Preferred Foot          18539 non-null  object
 19  National Team Name      18539 non-null  object
 20  National Team Position  18539 non-null  object
 21  Pace Total              18539 non-null  int64 
 22  Shooting Total          18539 non-null  int64 
 23  Passing Total           18539 non-null  int64 
 24  Dribbling Total         18539 non-null  int64 
 25  Defending Total         18539 non-null  int64 
 26  Physicality Total       18539 non-null  int64 
 27  Crossing                18539 non-null  int64 
 28  Finishing               18539 non-null  int64 
 29  Heading Accuracy        18539 non-null  int64 
 30  Short Passing           18539 non-null  int64 
 31  Volleys                 18539 non-null  int64 
 32  Dribbling               18539 non-null  int64 
 33  Curve                   18539 non-null  int64 
 34  Freekick Accuracy       18539 non-null  int64 
 35  LongPassing             18539 non-null  int64 
 36  BallControl             18539 non-null  int64 
 37  Acceleration            18539 non-null  int64 
 38  Sprint Speed            18539 non-null  int64 
 39  Agility                 18539 non-null  int64 
 40  Reactions               18539 non-null  int64 
 41  Balance                 18539 non-null  int64 
 42  Shot Power              18539 non-null  int64 
 43  Jumping                 18539 non-null  int64 
 44  Stamina                 18539 non-null  int64 
 45  Strength                18539 non-null  int64 
 46  Long Shots              18539 non-null  int64 
 47  Aggression              18539 non-null  int64 
 48  Interceptions           18539 non-null  int64 
 49  Positioning             18539 non-null  int64 
 50  Vision                  18539 non-null  int64 
 51  Penalties               18539 non-null  int64 
 52  Composure               18539 non-null  int64 
 53  Marking                 18539 non-null  int64 
 54  Standing Tackle         18539 non-null  int64 
 55  Sliding Tackle          18539 non-null  int64 
 56  Goalkeeper Diving       18539 non-null  int64 
 57  Goalkeeper Handling     18539 non-null  int64 
 58   GoalkeeperKicking      18539 non-null  int64 
 59  Goalkeeper Positioning  18539 non-null  int64 
 60  Goalkeeper Reflexes     18539 non-null  int64 
 61  ST Rating               18539 non-null  int64 
 62  LW Rating               18539 non-null  int64 
 63  LF Rating               18539 non-null  int64 
 64  CF Rating               18539 non-null  int64 
 65  RF Rating               18539 non-null  int64 
 66  RW Rating               18539 non-null  int64 
 67  CAM Rating              18539 non-null  int64 
 68  LM Rating               18539 non-null  int64 
 69  CM Rating               18539 non-null  int64 
 70  RM Rating               18539 non-null  int64 
 71  LWB Rating              18539 non-null  int64 
 72  CDM Rating              18539 non-null  int64 
 73  RWB Rating              18539 non-null  int64 
 74  LB Rating               18539 non-null  int64 
 75  CB Rating               18539 non-null  int64 
 76  RB Rating               18539 non-null  int64 
 77  GK Rating               18539 non-null  int64 
dtypes: int64(67), object(11)
memory usage: 11.0+ MB
In [8]:
df.isnull().sum()
Out[8]:
Known As      0
Full Name     0
Overall       0
Potential     0
Value         0
             ..
RWB Rating    0
LB Rating     0
CB Rating     0
RB Rating     0
GK Rating     0
Length: 78, dtype: int64

O Dataset não possui valores nulos e nem dados a serem tratados. 67 colunas são do tipo inteiro e 11 do tipo objeto (palavras).

In [9]:
df.describe()
Out[9]:
Overall Potential Value Age Height(in cm) Weight(in kg) TotalStats BaseStats Wage Release Clause Pace Total Shooting Total Passing Total Dribbling Total Defending Total Physicality Total Crossing Finishing Heading Accuracy Short Passing Volleys Dribbling Curve Freekick Accuracy LongPassing BallControl Acceleration Sprint Speed Agility Reactions Balance Shot Power Jumping Stamina Strength Long Shots Aggression Interceptions Positioning Vision Penalties Composure Marking Standing Tackle Sliding Tackle Goalkeeper Diving Goalkeeper Handling GoalkeeperKicking Goalkeeper Positioning Goalkeeper Reflexes ST Rating LW Rating LF Rating CF Rating RF Rating RW Rating CAM Rating LM Rating CM Rating RM Rating LWB Rating CDM Rating RWB Rating LB Rating CB Rating RB Rating GK Rating
count 18539.000000 18539.000000 1.853900e+04 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 1.853900e+04 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000 18539.000000
mean 65.852042 71.016668 2.875461e+06 25.240412 181.550839 75.173904 1602.114569 357.946221 8824.537462 5.081688e+06 68.017746 53.777874 58.024327 63.109553 50.241383 64.775338 49.476833 46.255300 51.846755 59.072226 42.513944 55.898754 47.695129 43.006689 53.568423 58.516263 64.725336 64.838341 63.518906 61.542586 64.059550 57.827661 64.795566 63.040455 65.152004 46.825719 55.668537 46.853282 50.520362 54.191542 47.994444 58.036625 46.747505 48.399159 46.264146 16.402125 16.157182 16.061007 16.205944 16.472895 56.725929 55.819138 55.714925 55.714925 55.714925 55.819138 57.950267 58.451319 57.374076 58.451319 56.281569 55.928583 56.281569 55.650251 54.528184 55.650251 23.257134
std 6.788353 6.192866 7.635129e+06 4.718163 6.858097 7.013593 273.160237 39.628259 19460.531154 1.467203e+07 10.649511 13.619867 9.717950 9.336566 16.392532 9.577715 17.887405 19.623881 17.318947 14.287698 17.635249 18.751691 17.910205 16.997758 14.633838 16.590051 15.280849 15.108259 14.905330 8.900297 14.483193 12.949870 12.293523 16.269330 12.622774 19.362064 16.905505 20.666647 19.660034 13.478006 15.730026 12.036272 20.350228 21.191644 20.701146 17.589457 16.924266 16.680839 17.089109 17.927602 13.475267 14.632018 14.216500 14.216500 14.216500 14.632018 13.905442 13.987122 13.171194 13.987122 13.903836 13.872190 13.903836 14.159466 14.743929 14.159466 15.108925
min 47.000000 48.000000 0.000000e+00 16.000000 155.000000 49.000000 759.000000 224.000000 0.000000 0.000000e+00 28.000000 16.000000 25.000000 28.000000 15.000000 30.000000 6.000000 3.000000 5.000000 10.000000 3.000000 3.000000 6.000000 4.000000 9.000000 5.000000 14.000000 15.000000 18.000000 30.000000 20.000000 18.000000 22.000000 14.000000 25.000000 4.000000 10.000000 3.000000 2.000000 10.000000 6.000000 13.000000 3.000000 6.000000 6.000000 2.000000 2.000000 2.000000 2.000000 2.000000 19.000000 14.000000 15.000000 15.000000 15.000000 14.000000 17.000000 18.000000 18.000000 18.000000 17.000000 19.000000 17.000000 17.000000 18.000000 17.000000 10.000000
25% 62.000000 67.000000 4.750000e+05 21.000000 177.000000 70.000000 1470.000000 331.000000 1000.000000 6.650000e+05 62.000000 44.000000 52.000000 58.000000 36.000000 58.000000 39.000000 31.000000 44.000000 55.000000 30.000000 51.000000 36.000000 32.000000 45.000000 55.000000 57.000000 57.000000 55.000000 56.000000 56.000000 48.000000 57.000000 56.000000 57.000000 32.000000 45.000000 26.000000 40.000000 45.000000 39.000000 51.000000 29.000000 28.000000 26.000000 8.000000 8.000000 8.000000 8.000000 8.000000 51.000000 50.000000 50.000000 50.000000 50.000000 50.000000 52.000000 54.000000 53.000000 54.000000 51.000000 48.000000 51.000000 49.000000 45.000000 49.000000 17.000000
50% 66.000000 71.000000 1.000000e+06 25.000000 182.000000 75.000000 1640.000000 358.000000 3000.000000 1.500000e+06 69.000000 56.000000 59.000000 64.000000 54.000000 66.000000 54.000000 50.000000 55.000000 62.000000 44.000000 61.000000 49.000000 42.000000 56.000000 63.000000 68.000000 68.000000 66.000000 62.000000 66.000000 59.000000 65.000000 66.000000 66.000000 51.000000 58.000000 54.000000 56.000000 56.000000 49.000000 59.000000 53.000000 56.000000 53.000000 11.000000 11.000000 11.000000 11.000000 11.000000 60.000000 59.000000 59.000000 59.000000 59.000000 59.000000 61.000000 62.000000 60.000000 62.000000 59.000000 59.000000 59.000000 59.000000 58.000000 59.000000 18.000000
75% 70.000000 75.000000 2.000000e+06 29.000000 186.000000 80.000000 1786.000000 385.000000 8000.000000 3.400000e+06 75.000000 64.000000 65.000000 69.000000 64.000000 72.000000 63.000000 62.000000 64.000000 68.000000 56.000000 68.000000 61.000000 55.000000 64.000000 69.000000 75.000000 75.000000 74.000000 67.000000 74.000000 68.000000 73.000000 74.000000 74.000000 62.000000 68.000000 64.000000 64.000000 64.000000 60.000000 66.000000 63.000000 66.000000 63.000000 14.000000 14.000000 14.000000 14.000000 14.000000 66.000000 65.000000 65.000000 65.000000 65.000000 65.000000 67.000000 67.000000 66.000000 67.000000 66.000000 66.000000 66.000000 65.000000 66.000000 65.000000 20.000000
max 91.000000 95.000000 1.905000e+08 44.000000 206.000000 105.000000 2312.000000 502.000000 450000.000000 3.667000e+08 97.000000 92.000000 93.000000 94.000000 91.000000 91.000000 94.000000 94.000000 93.000000 93.000000 90.000000 95.000000 93.000000 94.000000 93.000000 94.000000 97.000000 97.000000 94.000000 94.000000 95.000000 94.000000 95.000000 95.000000 96.000000 91.000000 95.000000 91.000000 96.000000 94.000000 92.000000 96.000000 92.000000 93.000000 90.000000 90.000000 90.000000 93.000000 91.000000 90.000000 92.000000 90.000000 91.000000 91.000000 91.000000 90.000000 92.000000 92.000000 91.000000 92.000000 88.000000 89.000000 88.000000 87.000000 90.000000 87.000000 90.000000

Agora que temos uma visão geral sobre como os dados são, podemos analisar de forma mais específica, começando pela análise univariada.

4. Análise Univariada¶

Análise de certas variáveis individualmente, vendo suas quantidades e distribuições.

In [40]:
#Criando um gráfico de barra
fig = px.bar(df.Nationality.value_counts().head(10), y = 'Nationality',title = 'Países com mais jogadores no Game')
fig.update_layout(xaxis_title = 'Países')
fig.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[40], line 6
      4 fig.update_layout(yaxis_title = 'Quantidade')
      5 pyo.iplot(fig)
----> 6 fig.write_image("plot.png")

File ~\anaconda3\lib\site-packages\plotly\basedatatypes.py:3829, in BaseFigure.write_image(self, *args, **kwargs)
   3769 """
   3770 Convert a figure to a static image and write it to a file or writeable
   3771 object
   (...)
   3825 None
   3826 """
   3827 import plotly.io as pio
-> 3829 return pio.write_image(self, *args, **kwargs)

File ~\anaconda3\lib\site-packages\plotly\io\_kaleido.py:268, in write_image(fig, file, format, scale, width, height, validate, engine)
    252             raise ValueError(
    253                 """
    254 Cannot infer image type from output path '{file}'.
   (...)
    262                 )
    263             )
    265     # Request image
    266     # -------------
    267     # Do this first so we don't create a file if image conversion fails
--> 268     img_data = to_image(
    269         fig,
    270         format=format,
    271         scale=scale,
    272         width=width,
    273         height=height,
    274         validate=validate,
    275         engine=engine,
    276     )
    278     # Open file
    279     # ---------
    280     if path is None:
    281         # We previously failed to make sense of `file` as a pathlib object.
    282         # Attempt to write to `file` as an open file descriptor.

File ~\anaconda3\lib\site-packages\plotly\io\_kaleido.py:134, in to_image(fig, format, width, height, scale, validate, engine)
    132     # Raise informative error message if Kaleido is not installed
    133     if scope is None:
--> 134         raise ValueError(
    135             """
    136 Image export using the "kaleido" engine requires the kaleido package,
    137 which can be installed using pip:
    138     $ pip install -U kaleido
    139 """
    140         )
    142     # Validate figure
    143     # ---------------
    144     fig_dict = validate_coerce_fig_to_dict(fig, validate)

ValueError: 
Image export using the "kaleido" engine requires the kaleido package,
which can be installed using pip:
    $ pip install -U kaleido

O Fato de a Inglaterra possuir mais jogadores registrados não quer dizer necessariamente que o país possui a maior quantidade de jogadores profissionais - apesar dos vários indícios para isso. Essa grande quantidade existe porque existem muitas ligas inglesas inferiores cadastradas no jogo. Ao contrário, por exemplo, do Brasil, que possui não possui nenhuma liga nacional registrada de forma oficial (apenas com alguns jogadores gerados pelo jogo).

In [11]:
#Criando uma função que gera um conjunto de gráficos
fig2 = make_subplots(rows =2 , cols =2)

#Adicionando gráficos de histograma
fig2.add_trace(go.Histogram(x=df['Overall'], name = "Distribuição de Overall por jogadores") ,row =1, col=1)
fig2.add_trace(go.Histogram(x=df['Potential'], name = "Distribuição de Potencial dos jogadores") ,row =1, col=2)
fig2.add_trace(go.Histogram(x=df['Overall'], name = 'Overall') ,row =2, col=1)
fig2.add_trace(go.Histogram(x=df['Potential'], name = 'Potencial') ,row =2, col=1)

#Mudando suas características
fig2.update_xaxes(title_text="Overall", row=1, col=1)
fig2.update_xaxes(title_text="Potencial", row=1, col=2)
fig2.update_xaxes(title_text="Overall x Potencial", row=2, col=1)
fig2.update_layout(height=900, width=1000)

pyo.iplot(fig2)

Para vermos os jogadores com maiores ratings por posição , criei duas funções: uma para achar o nome e outro o rating do jogador. Por fim criando uma tabela (DataFrame) com todas essas informações.

In [12]:
#Função para retornar os nomes do jogadores
def get_max_name(df, col):   
    return df.iloc[df[col].idxmax(), 0]

#Função para retornar os maiores ratings 
def get_max_rat(df, col):
    return list(df.loc[df[col].max(), col].index)

#Criando variáveis com os nomes e ratings maiores
max_names = get_max_name(df,df.columns[61:78])
max_rats = get_max_rat(df, df.columns[61:78])

#Criando Dataframe com as variáveis importantes
top_ply = pd.DataFrame({'Jogador':max_names, 'Posição': df.columns[61:78], 'Rating' : max_rats})
top_ply
Out[12]:
Jogador Posição Rating
4 K. Mbappé ST Rating 92
0 L. Messi LW Rating 90
0 L. Messi LF Rating 91
0 L. Messi CF Rating 91
0 L. Messi RF Rating 91
0 L. Messi RW Rating 90
4 K. Mbappé CAM Rating 92
4 K. Mbappé LM Rating 92
3 K. De Bruyne CM Rating 91
4 K. Mbappé RM Rating 92
24 João Cancelo LWB Rating 88
13 Casemiro CDM Rating 89
24 João Cancelo RWB Rating 88
19 N. Kanté LB Rating 87
9 V. van Dijk CB Rating 90
19 N. Kanté RB Rating 87
6 T. Courtois GK Rating 90
In [13]:
#Criando histograma para ver a distribuição de idade
fig3 = px.histogram(df, x = 'Age',title = 'Distribuição de Idade')
fig3.update_layout(xaxis_title = 'Idade')
fig3.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig3)

Diversos jogadores podem atuar bem em posições diferentes, mas vamos ver quais são as mais comuns pelo atributo "Best Position", que contém a melhor posição que os atletas podem atuar.

In [14]:
#Criando gráfico com as posições mais frequentes no jogo
fig4 = px.histogram(df, x = 'Best Position', color = 'Best Position', title = 'Posições mais frequentes')
fig4.update_layout(xaxis_title = 'Melhor Posição')
fig4.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig4)

Vemos que, as quatro posições com mais jogadores especialistas são CB (Center back) que significa zagueiro, ST (Striker) atacante, CAM (Central Attack Midfielder) meio-campista avançado e GK (Goalkeeper).

Para verificarmos quais países possuem as maiores médias de overall, temos que nos atentar ao fato de que existem alguns países com poucos jogadores, fazendo com que eles tenham uma média maior mesmo sem possuir realmente bons jogadores ou alguma relevância no esporte. Por isso, analisaremos apenas as médias de países possuem pelo menos 150 jogadores no jogo. Para isso, criei um dataframe (dfb) com as nações e a quantidade de jogadores em cada uma para poder extrair apenas seus nomes e aplicar a função "isin", selecionando só jogadores dessas nações.

In [15]:
# Criando dataframe com países de pelo menos 150 jogadores
dfb = df.groupby("Nationality").size().reset_index(name='counts')
dfb = dfb[dfb['counts'] > 150]

# Lista contendo os países com mais de 150 jogadores
b = dfb.iloc[:, 0]
dfb = df[df['Nationality'].isin(b)]

# Gerando gráfico
ovr_nat = dfb.groupby('Nationality').Overall.mean().sort_values(ascending = False)
fig5 = px.bar(ovr_nat.head(10), title = 'Países por média de Overall')
fig5.update_layout(xaxis_title = 'Nacionalidade')
fig5.update_layout(yaxis_title = 'Média de OVR')
pyo.iplot(fig5)

Mesmo filtrando os países, ainda temos países com médias que não condizem exatamente com a qualidade geral de suas seleções. Isso acontece porque, como vimos anteriormente, países com França, Alemanha e Inglaterra (três dos mais tradicionais) têm muitos jogadores, o que os faz ter uma média de Overall menor, já que têm jogadores em ligar inferiores. Outra forma de atingir o mesmo objetivo (talvez até melhor) é contar a quantidade de jogadores com mais de 70 de Overall por cada país. Dessa forma, temos um retrato mais fiel da realidade, com os países considerados mais talentosos acima - incluindo o Brasil em primeiro :).

In [16]:
#Criando dataframe com apenas jogadores de pelo menos 70 de Overall e de países com pelo menos 150 jogadores
dfb = df.groupby("Nationality").size().reset_index(name='counts')
dfc = dfb[dfb['counts'] > 150]
dfc = df[df['Nationality'].isin(dfb['Nationality'])]
dfc = dfc[dfc['Overall'] > 70]

#Criando variável com a quantidade de jogadores por país e um gráfico de barras
ovr_count = dfc['Nationality'].value_counts()
fig8 = px.bar(ovr_count.head(10))
fig8.update_traces(marker=dict(color='yellow'))
fig8.update_layout(xaxis_title = 'Nacionalidade')
fig8.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig8)

Seguindo a mesma métrica, veremos os países com maior overall potencial (promessas), ou seja, os que têm mais jogadores promissores, que o FIFA prevê que iram evoluir mais no futuro e se tornarem bons jogadores. Escolheremos apenas os que tem potencial maior que 80 e que possuem menos de 23 anos.

In [17]:
#Criando variável contendo jogadores com no máximo 23 anos e potencial de pelo menos 80 de Overall
prom = df[(df['Potential'] >= 80) & (df['Age'] <= 23)]
prom = prom['Nationality'].value_counts()

#Criando gráfico
fig9 = px.bar(prom.head(10), title = 'Países com jogadores jovens acima de 80 de Overall potencial')
fig9.update_traces(marker=dict(color='blue'))
fig9.update_layout(xaxis_title = 'Países')
fig9.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig9)

Agora contando jogadores com potencial de se tornarem grandes estrelas, com 90 ou mais de overall potencial.

In [18]:
#Criando variável contendo jogadores com no máximo 23 anos e Overall potencial de 90
stars = df[(df['Potential'] >= 90) & (df['Age'] <= 23)]
stars = stars['Nationality'].value_counts()

#Criando gráfico
fig10 = px.bar(stars.head(10), title = 'Países com mais jogadores com 90 ou mais de Overall')
fig10.update_traces(marker=dict(color='green'))
fig10.update_layout(xaxis_title = 'Países')
fig10.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig10)

Vale lembrar que prever o desenvolvimento de um jogador é uma tarefa bem difícil, pois nem sempre eles evoluem como o previsto. Além disso, existem vários jovens surgindo sempre, incluindo em ligas não cadastradas no jogo ou em categorias de base (por isso países com alta revelação de bons jogadores como Argentina e Brasil não aparecem com tanto destaque). Portanto, é errado entender esses dados como extremamente precisos, já que o potencial de um atleta é flexível e imprevisivel.

Agora focaremos mais nos clubes, começando pelos que tem mais jogadores, depois overall médio e folhas salariais.

In [19]:
#Excluindo jogadores "Free agent" (Sem clube)
dfd = df[df['Club Name'] != 'Free agent']

#Criando variável que contém a quantidade de jogadores por clube
clubs = dfd['Club Name'].value_counts()

#Criando gráfico
fig11 = px.bar(clubs.head(10), title = 'Clubes com mais jogadores')
fig11.update_layout(xaxis_title = 'Clubes')
fig11.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig11)
In [20]:
#Aqui excluí um time que ficou com a média alta por ter poucos jogadores
dfe = df[df['Club Name'] != 'AFC Richmond']

#Criando variável com os valores ordenados das clubes com maiores médias de Overall
clubs_ovr = dfe.groupby('Club Name').Overall.mean().sort_values(ascending = False)

#Criando gráfico
fig12 = px.bar(clubs_ovr.head(10), title = 'Clubes por Overall')
fig12.update_layout(xaxis_title = 'Clubes')
fig12.update_layout(yaxis_title = 'Quantidade')
fig12.update_traces(marker=dict(color='purple'))
pyo.iplot(fig12)

Veremos os clubes mais valiosos a partir da soma dos salários de todos os jogadores (folha salarial).

In [21]:
#Criando variável agrupando por clube e ordenando pelo valor da soma dos salários
sals = df.groupby('Club Name')['Wage'].sum().sort_values(ascending = False)

#Criando gráfico
fig13 = px.bar(sals.head(), title = 'Clubes mais valiosos')
fig13.update_layout(xaxis_title = 'Clubes')
fig13.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig13)

5. Análise Multivariada¶

Nesse tipo de análise vemos as interações entre duas ou mais variáveis, medindo suas correlações e dispersões. Primeiramente, utilizaremos a função "corr" do pandas para ver as correlações entre as colunas.

A correlação de Pearson (ou simplesmente "correlação") é uma estatística descritiva que mede o grau de associação entre duas variáveis, indo de -1 (correlação negativa) e 1 (correlação perfeita). Quanto mais próximo de 1, maior a correlação entre duas variáveis e, quanto mais próximo de -1 menor ela é. Porém, caso o valor seja próximo ou igual a zero, não há correlação linear entre as variáveis, só podendo existir uma correlação não-linear.

In [22]:
#Calculando a correlação geral do Dataframe
df.corr(numeric_only = True)
Out[22]:
Overall Potential Value Age Height(in cm) Weight(in kg) TotalStats BaseStats Wage Release Clause Pace Total Shooting Total Passing Total Dribbling Total Defending Total Physicality Total Crossing Finishing Heading Accuracy Short Passing Volleys Dribbling Curve Freekick Accuracy LongPassing BallControl Acceleration Sprint Speed Agility Reactions Balance Shot Power Jumping Stamina Strength Long Shots Aggression Interceptions Positioning Vision Penalties Composure Marking Standing Tackle Sliding Tackle Goalkeeper Diving Goalkeeper Handling GoalkeeperKicking Goalkeeper Positioning Goalkeeper Reflexes ST Rating LW Rating LF Rating CF Rating RF Rating RW Rating CAM Rating LM Rating CM Rating RM Rating LWB Rating CDM Rating RWB Rating LB Rating CB Rating RB Rating GK Rating
Overall 1.000000 0.660630 0.561642 0.442369 0.033137 0.131420 0.608002 0.843720 0.599129 0.531458 0.252837 0.465057 0.699315 0.674971 0.362324 0.560813 0.395435 0.331967 0.342452 0.520784 0.367168 0.376185 0.416575 0.374162 0.507192 0.457705 0.198758 0.213367 0.254826 0.872789 0.142749 0.552518 0.282737 0.376994 0.353857 0.392187 0.393433 0.311216 0.348038 0.523290 0.331834 0.700583 0.313975 0.266683 0.240499 -0.016593 -0.013655 -0.016764 -0.008318 -0.013110 0.480301 0.447831 0.475105 0.475105 0.475105 0.447831 0.489274 0.472606 0.541536 0.472606 0.451583 0.479747 0.451583 0.428254 0.400783 0.428254 0.044462
Potential 0.660630 1.000000 0.532835 -0.263686 0.017489 -0.003973 0.372469 0.526546 0.497392 0.509867 0.288590 0.281073 0.448553 0.501373 0.180526 0.205186 0.244649 0.227078 0.195108 0.376854 0.228954 0.302802 0.269170 0.207204 0.338221 0.346017 0.220052 0.225343 0.205465 0.539246 0.131779 0.337282 0.087303 0.187141 0.081426 0.232690 0.186599 0.155149 0.226827 0.352757 0.201297 0.427722 0.157665 0.156970 0.142714 -0.039719 -0.040237 -0.040616 -0.037519 -0.038448 0.330398 0.326722 0.339944 0.339944 0.339944 0.326722 0.359247 0.348049 0.370327 0.348049 0.291078 0.294840 0.291078 0.270494 0.227643 0.270494 -0.002057
Value 0.561642 0.532835 1.000000 0.030662 0.008028 0.027106 0.341551 0.468076 0.822262 0.976244 0.205576 0.275255 0.399985 0.406424 0.163425 0.234945 0.230049 0.216025 0.167989 0.304244 0.233128 0.241773 0.253454 0.210590 0.291490 0.273427 0.159242 0.166743 0.170707 0.498667 0.120730 0.303484 0.112006 0.197522 0.129648 0.227479 0.187351 0.145640 0.220491 0.329637 0.190236 0.391234 0.145681 0.131331 0.112650 -0.026560 -0.026122 -0.024337 -0.024374 -0.023352 0.292802 0.279449 0.293238 0.293238 0.293238 0.279449 0.306244 0.295886 0.321575 0.295886 0.252712 0.259591 0.252712 0.234933 0.202809 0.234933 0.011339
Age 0.442369 -0.263686 0.030662 1.000000 0.066684 0.217895 0.246279 0.381901 0.144251 0.025078 -0.144474 0.253085 0.338708 0.215832 0.225600 0.440695 0.124869 0.083500 0.156620 0.144434 0.138420 0.024946 0.141496 0.180766 0.188503 0.089223 -0.135626 -0.125666 -0.019026 0.434187 -0.050771 0.267892 0.236982 0.133382 0.343639 0.155305 0.239378 0.173657 0.092903 0.200278 0.144097 0.348245 0.168584 0.106238 0.093218 0.100972 0.106347 0.102898 0.111290 0.104034 0.132588 0.086605 0.111920 0.111920 0.111920 0.086605 0.108152 0.091072 0.166533 0.091072 0.141274 0.193036 0.141274 0.142184 0.183151 0.142184 0.132966
Height(in cm) 0.033137 0.017489 0.008028 0.066684 1.000000 0.754845 -0.382480 -0.123239 0.025430 0.006404 -0.373351 -0.084751 -0.180343 -0.271559 0.037421 0.409400 -0.501520 -0.382351 0.008303 -0.342818 -0.355246 -0.480466 -0.457941 -0.430508 -0.319053 -0.402082 -0.543262 -0.448808 -0.633949 0.001989 -0.767247 -0.169045 0.026047 -0.300078 0.522558 -0.399726 -0.073005 -0.094095 -0.446303 -0.369882 -0.341398 -0.184355 -0.099398 -0.110241 -0.111459 0.366696 0.364998 0.362319 0.361931 0.363832 -0.368263 -0.480017 -0.438248 -0.438248 -0.438248 -0.480017 -0.449370 -0.464597 -0.387355 -0.464597 -0.321388 -0.212100 -0.321388 -0.271875 -0.088695 -0.271875 0.369929
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
RWB Rating 0.451583 0.291078 0.252712 0.141274 -0.321388 -0.257192 0.885559 0.470957 0.271175 0.238489 0.151705 -0.160019 0.259710 0.159003 0.723959 0.349887 0.795186 0.479392 0.709170 0.869402 0.513274 0.758276 0.686218 0.619042 0.830357 0.824810 0.591191 0.593017 0.570948 0.476829 0.532420 0.355972 0.341459 0.838713 0.254454 0.592792 0.791688 0.853604 0.638783 0.524084 0.514528 0.682670 0.862314 0.859867 0.841383 -0.766415 -0.763568 -0.763878 -0.761488 -0.765552 0.732549 0.769684 0.746306 0.746306 0.746306 0.769684 0.780057 0.819394 0.896510 0.819394 1.000000 0.977241 1.000000 0.993319 0.927139 0.993319 -0.744169
LB Rating 0.428254 0.270494 0.234933 0.142184 -0.271875 -0.215549 0.840970 0.433111 0.253928 0.222359 0.100806 -0.235150 0.204396 0.082624 0.783949 0.384640 0.736066 0.400156 0.718136 0.828250 0.441013 0.690395 0.619006 0.556380 0.798432 0.770106 0.538110 0.547548 0.504430 0.455845 0.476196 0.291748 0.364581 0.815013 0.290724 0.521038 0.809376 0.896324 0.566065 0.452945 0.450396 0.644653 0.903601 0.905184 0.889880 -0.745071 -0.742363 -0.743158 -0.740329 -0.744323 0.668854 0.700366 0.676994 0.676994 0.676994 0.700366 0.712892 0.755647 0.849648 0.755647 0.993319 0.984470 0.993319 1.000000 0.959383 1.000000 -0.724081
CB Rating 0.400783 0.227643 0.202809 0.183151 -0.088695 -0.044569 0.720341 0.353803 0.229538 0.192411 -0.090421 -0.346965 0.101544 -0.070391 0.877260 0.521944 0.557062 0.229739 0.742060 0.723283 0.287786 0.515448 0.449180 0.407878 0.712590 0.629772 0.334348 0.363651 0.294975 0.432366 0.282916 0.185968 0.430265 0.721308 0.450186 0.364031 0.856911 0.947824 0.393360 0.301049 0.315045 0.571834 0.953673 0.953278 0.937945 -0.656437 -0.653725 -0.655322 -0.651969 -0.655857 0.520290 0.519606 0.507501 0.507501 0.507501 0.519606 0.545751 0.584842 0.725680 0.584842 0.927139 0.967690 0.927139 0.959383 1.000000 0.959383 -0.635901
RB Rating 0.428254 0.270494 0.234933 0.142184 -0.271875 -0.215549 0.840970 0.433111 0.253928 0.222359 0.100806 -0.235150 0.204396 0.082624 0.783949 0.384640 0.736066 0.400156 0.718136 0.828250 0.441013 0.690395 0.619006 0.556380 0.798432 0.770106 0.538110 0.547548 0.504430 0.455845 0.476196 0.291748 0.364581 0.815013 0.290724 0.521038 0.809376 0.896324 0.566065 0.452945 0.450396 0.644653 0.903601 0.905184 0.889880 -0.745071 -0.742363 -0.743158 -0.740329 -0.744323 0.668854 0.700366 0.676994 0.676994 0.676994 0.700366 0.712892 0.755647 0.849648 0.755647 0.993319 0.984470 0.993319 1.000000 0.959383 1.000000 -0.724081
GK Rating 0.044462 -0.002057 0.011339 0.132966 0.369929 0.344316 -0.648967 0.078930 0.013433 0.014015 -0.060873 0.288931 0.220301 0.187807 -0.261143 0.023738 -0.667654 -0.605826 -0.738352 -0.716263 -0.594482 -0.768641 -0.616438 -0.569212 -0.579861 -0.787955 -0.635932 -0.637259 -0.563696 -0.022147 -0.540291 -0.245527 -0.213373 -0.695350 -0.111834 -0.610950 -0.588176 -0.506051 -0.693344 -0.328987 -0.622415 -0.432213 -0.548571 -0.550053 -0.531734 0.987338 0.986737 0.978658 0.986624 0.987912 -0.728235 -0.738402 -0.717813 -0.717813 -0.717813 -0.738402 -0.717090 -0.750672 -0.725650 -0.750672 -0.744169 -0.677267 -0.744169 -0.724081 -0.635901 -0.724081 1.000000

67 rows × 67 columns

Como temos muitas linhas e colunas, fica difícil conseguir analisar bem essa tabela de correlação, mas veremos as mais importantes mais à frente. Por enquanto olharemos os gráficos de dispersão de algumas variáveis relevantes.

In [23]:
#Criando gráfico de dispersão entre overall e idade
figb = px.scatter(df, x = 'Overall', y = 'Age', color = 'Overall', title = 'Overall por Idade', trendline="ols")
figb.update_layout(yaxis_title='Idade')
pyo.iplot(figb)

Aqui observamos que existe uma tendência natural, e esperada, de crescimento do Overall conforme o aumento da idade. Apenas um jogador com menos de 25 anos possui mais de 90 de rating e somente um com mais de 40 anos tem um rating próximo a 80.

In [24]:
#Criando gráfico de dispersão entre salário e overall
figc = px.scatter(df, x='Wage', y='Overall', color='Wage', trendline = "ols", title = 'Salário x Overall')
figc.update_layout(xaxis_title='Salário')
pyo.iplot(figc)

Nesta dispersão, também vemos uma natural correlação positiva entre Overall e Salário, apesar de alguns valores discrepantes dos demais.

In [25]:
#Criando gráfico
figd = px.scatter(df, x='Value', y='Age', color='Value', trendline = 'ols', title ='Valor x Idade')
figd.update_layout(xaxis_title='Valor')
figd.update_layout(yaxis_title='Idade')
pyo.iplot(figd)

Na relação entre Idade e Valor, constatamos que existe uma correlação linear um pouco mais baixa do que se poderia imaginar. Com o passar do tempo, é natural que os atletas percam seu valor de mercado, já que seus atributos físicos costumam diminuir. Esse fenômeno ocorre aqui, mas não de forma linear, o que nos faz crer que existe uma correlação não-linear entre as duas variáveis. Outro fator que contribui para isso é que Overall e Idade não são necessariamente proporcionais, ou seja, parte considerável dos jogadores mantém suas qualidades por mais tempo.

In [26]:
#Criando gráfico
fige = px.scatter(df, x ='Potential', y = 'Value', color='Value', trendline = 'ols')
pyo.iplot(fige)

Apesar de alguns valores discrepantes, aqui também não vemos nada anormal, jogadores com maior potencial valem mais no mercado.

Para checarmos a distribuição salarial dos 5 clubes mais valiosos, usaremos o boxplot. Basicamente, as extremidades são os valores maiores e menores , a mediana dos valores é o traço dentro do retângulo ("box") e extremidades dele são o primeiro (parte inferior) e terceiro (parte superior) quartis, que representam - respectivamente-, 25% e 75% dos valores.

In [27]:
#Criando Dataframe apenas com o jogadores dos 5 clubes mais valiosos
df_clbs = df_clubs = df[df['Club Name'].isin(['Real Madrid CF', 'Manchester City', 'FC Barcelona',
                                               'Liverpool', 'Manchester United'])]

#Criando gráfico boxplot
fig14 = px.box(df_clbs, x = 'Club Name', y = 'Wage', title = 'Distribuição de salários entre os 5 primeiros em folha salarial')
fig14.update_layout(xaxis_title = 'Clubes')
fig14.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig14)

O ponto fora do gráfico Boxplot do Barcelona representa um Outlier (Valor discrepante em relação aos demais), o que indica que existe uma certa disparidade salarial no clube. O gráfico do Real Madrid também possui pontos bem altos, porém, como não existem Outliers, entendemos que a diferença entre os salários não é tão grande e, caso exista, não é responsável por apenas um jogador como no caso do Barcelona.

6. Respondendo as perguntas e hipóteses restantes¶

Agora que já temos uma boa visão geral sobre o conjunto de dados, podemos tentar buscar respostas para nossas perguntas e hipóteses criadas no início da análise. Primeiro tentando identificar quais são os jogadores mais habilidosos e velozes do game.

-> Quais são os jogadores mais rápidos e habilidosos?

Para isso, escolheremos colunas que representam atributos relacionados a velocidade e habilidade geral. Como: Pace Total, Dribbling Total, Dribbling, etc...

In [28]:
hab = df.loc[:, ['Known As','Nationality', 'Pace Total', 'Dribbling Total', 'Dribbling', 'Acceleration', 'Sprint Speed', 
                 'Agility', 'Reactions', 'BallControl', 'Balance']]
hab.rename(columns = {'Known As': 'Jogador', 'Nationality':'Nacionalidade'}, inplace = True)
hab['Habilidade Geral'] = (hab['Dribbling Total']  + hab['Reactions'] + hab['Dribbling'] + hab['BallControl'] + hab['Balance'])/5
hab['Velocidade Geral'] = (hab['Pace Total'] +  hab['Acceleration'] + hab['Agility'] + hab['Reactions'] + hab['Sprint Speed'])/5
In [29]:
top_hab = hab.sort_values(by = 'Habilidade Geral', ascending = False)
top_hab.head(10).loc[:, ['Jogador', 'Nacionalidade', 'Habilidade Geral']]

# JOGADORES COM MAIS HABILIDADE GERAL
Out[29]:
Jogador Nacionalidade Habilidade Geral
0 L. Messi Argentina 93.8
36 M. Verratti Italy 90.8
23 Bernardo Silva Portugal 90.8
11 Neymar Jr Brazil 90.4
5 M. Salah Egypt 90.4
4 K. Mbappé France 90.0
43 Thiago Spain 89.0
29 L. Modrić Croatia 88.6
48 R. Mahrez Algeria 88.4
49 P. Dybala Argentina 88.4
In [30]:
top_spd = hab.sort_values(by = 'Velocidade Geral', ascending = False)
top_spd.head(10).loc[:, ['Jogador', 'Nacionalidade', 'Velocidade Geral']]

# JOGADORES COM MAIS VELOCIDADE GERAL
Out[30]:
Jogador Nacionalidade Velocidade Geral
4 K. Mbappé France 95.4
63 Vinícius Jr. Brazil 92.2
15 S. Mané Senegal 91.0
47 R. Sterling England 91.0
56 K. Coman France 90.8
141 A. Davies Canada 90.6
5 M. Salah Egypt 90.6
402 J. Frimpong Netherlands 90.0
155 O. Dembélé France 89.6
1109 F. Acheampong Ghana 89.6

-> Jogadores brasileiros (ou sulamericanos) são naturalmente mais habilidosos que os de outras nações.

Com esses dados de habilidade geral, que inclui os atributos: Dribbling Total (Média dos atributos de drible), Reactions (Velocidade de reação), Dribbbling (Drible), Ball Control (Controle de Bola) e Balance (Controle de bola após uma disputa - influencia o drible), podemos validar ou não esta hipótese.

In [31]:
# Criando dataframe com países e quantidade de jogadores
dfg = df.groupby("Nationality").size().reset_index(name='counts')
dfg = dfg[dfg['counts'] > 150]

# Lista contendo os países com mais de 100 jogadores
g = dfg.iloc[:, 0]

nac_hab = top_hab[top_hab['Nacionalidade'].isin(g)]
nac_hab = nac_hab.groupby('Nacionalidade')['Habilidade Geral'].mean()
nac_hab = nac_hab.sort_values(ascending = False)

fig15 = px.bar(nac_hab.head(10), title = 'Média de Habilidade Geral por país')
fig15.update_traces(marker=dict(color='gold'))
fig15.update_layout(xaxis_title = 'Países')
fig15.update_layout(yaxis_title = 'Quantidade')
pyo.iplot(fig15)

Como podemos ver, a hipótese é verdadeira , os jogadores brasileiros aparecem (com uma leve diferença) em primeiro no gráfico, que também contém mais dois países sulamericanos no top 5 (Argentina e Colômbia).

-> Jogadores com maiores TotalStats (Soma de todos os atributos) possuem Overalls mais altos.

Isso é lógico de se pensar, já que a nota de Overall reflete a qualidade dos atributos do jogador. Mas será que essas duas métricas são realmente proporcionais?

In [32]:
#Criando Dataframe só com as colunas TotalStats e Overall
sta_ovr = df.loc[:, ['TotalStats', 'Overall']]

#Criando gráfico de dispersão
fig16 = px.scatter(sta_ovr, x = 'Overall', y = 'TotalStats', color = 'TotalStats', trendline="ols")
pyo.iplot(fig16)
In [33]:
#Calculando a correlação geral
sta_ovr.corr()
Out[33]:
TotalStats Overall
TotalStats 1.000000 0.608002
Overall 0.608002 1.000000

Aplicando o scatter plot entre Overall e TotalStats e usando o atributo "trendline = ols", observamos que há uma relação linear (estimada pela linha) entre essas duas características com o R-quadrado aproximadamente igual a 37% (0,369). Neste caso, esse valor representa o quão bem a variação do Overall acompanha a variação do TotalStats. Já a correlação indica a força da relação entre as variáveis, variando entre -1 (Correlação Negativa) e 1 (Correlação Positiva), que foi de 0,608. Conclusão: existe uma correlação, mas ela é menor do que naturalmente se espera.

Já que não tivemos uma correspondência tão grande entre TotalStats e os ratings dos jogadores, podemos verificar o mesmo para o atributo BaseStats, que é equivalente a soma dos atributos Pace Total (Média dos atributos de velocidade), Shooting Total (Média dos atributos de chute), Passing Total (Média dos atributos de passe), Dribbling Total (Média dos atributos de drible), Defending Total (Média dos atributos de defesa) e Physicality Total (Média dos atributos físicos).

Como o BaseStats só leva em conta poucos dados (ao contrário do TotalStats), é natural que observemos uma correlação mais próxima de 1 (positiva) e um gráfico de dispersão que evidencie isso.

In [34]:
#Criando gráfico de dispersão
fig17 = px.scatter(df, x = 'Overall', y = 'BaseStats', color = 'Overall', title = 'BaseStats x Overall', trendline = 'ols')
pyo.iplot(fig17)
In [35]:
#Criando Dataframe só com BaseStats e overall
Bsta = df.loc[:, ['BaseStats', 'Overall']]

#Calculando correlação
Bsta.corr()
Out[35]:
BaseStats Overall
BaseStats 1.00000 0.84372
Overall 0.84372 1.00000

Agora, com BaseStats, vemos uma relação mais consistente entre as variáveis. Através da trendline, observamos que o R-quadrado é de 0.711 (71,1%), o que indica uma boa relação linear e, pela função corr, uma correlação de 0.84 (0.2 maior que a da TotalStats). Com isso, concluímos que esse atributo reflete mais a qualidade dos atletas no game.

-> Atributos que mais contribuem com o rating (Overall)

In [36]:
#Criando Dataframes com as colunas de atributos e a de Overall
att = df.iloc[:, 21:61]
ovr = df['Overall']

#Juntando os Dataframes
att = pd.concat([ovr, att], axis = 1)

#Calculando a correlação entre Overall e atributos e ordenando os valores
corrs1 = att.corr(numeric_only = True)
corrs = corrs1['Overall'].sort_values(ascending = False)
In [37]:
#Vendo os 10 maiores valores
corrs.head(10)
Out[37]:
Overall              1.000000
Reactions            0.872789
Composure            0.700583
Passing Total        0.699315
Dribbling Total      0.674971
Physicality Total    0.560813
Shot Power           0.552518
Vision               0.523290
Short Passing        0.520784
LongPassing          0.507192
Name: Overall, dtype: float64

Como resultado, temos que os atributos com maior influência no rating de um jogador são: Reactions (Velocidade de reação), Composure (Controle mental), Passing Total (Média de atributos de passe) e Dribbling Total (Média de atributos de drible). Após isso, Physicality Total (Média dos atributos físicos), Shot Power (Força de chute), dentre outros. A conclusão que temos é que, além de atributos físicos, os melhores jogadores também possuem uma boa mentalidade e habilidade emocional.

In [38]:
#Vendo os 10 menores valores
corrs.tail(10)
Out[38]:
Pace Total                0.252837
Sliding Tackle            0.240499
Sprint Speed              0.213367
Acceleration              0.198758
Balance                   0.142749
Goalkeeper Positioning   -0.008318
Goalkeeper Reflexes      -0.013110
Goalkeeper Handling      -0.013655
Goalkeeper Diving        -0.016593
 GoalkeeperKicking       -0.016764
Name: Overall, dtype: float64

Entre os atributos menos correlacionados, naturalmente estão os que pertencem aos goleiro, mas também os relacionados a velocidade.

Por fim, criei uma mapa de calor para entendermos a correlação geral entre os atributos e o Overall, onde as cores mais claras representam uma correlação mais forte.

In [39]:
#Criando um mapa de calor
heat = px.imshow(corrs1)
heat.update_layout(height = 600, width = 790)
pyo.iplot(heat)

7. Considerações finais¶

Apesar de não ser um conjunto de dados complexo e um pouco distante da realidade e seus problemas, acredito que foi possível tirar bons insigths e testar algumas coisa com eles. Além de uma análise exploratória, é possível também aplicar técnicas mais avançadas de estatística e machine learning para, por exemplo, fazer previsões sobre o salário ou o valor de algum jogador baseado em seus atributos e características. Além de sistemas de recomendação das melhores escalações ou de jogadores para serem comprados pelos usuários em suas gameplays e análise para a descobertas de jogadores com potencial de crescimento elevado e que podem se tornam atletas de elite no cenário internacional.

Creio que atingi todos os objetivos que criei e utilizei as melhores maneiras de visualização de dados que tenho conhecimento (ponto que pode ser melhorado ainda mais). Por ser meu projeto desse tipo, fiquei com bastante dúvida sobre o que colocar e aceito sugestões e feedback sobre minha análise. Pretendo fazer mais projetos como esse, além de outros voltados a machine learning (regressão, classificação, clusterização, etc..) no futuro a partir da continuação dos meus estudos sobre data science. Muito obrigado por ler e até mais! ;)